/**
 * The Calendar user-interface component class
 * @class syslib.ui.Calendar
 * @author Gabriel Ricci
 */
syslib.ui.Calendar = __class(syslib.ui.VisualTag, 
/**
 * @lends syslib.ui.Calendar
 */
{
	drag: null,
	calendar : null, 
	
	name : "", 
	id : "", 
	value : "", 
	
	today : new Date(), 
	workDate  : new Date(),
	
	controller : null,
	input : null,
	format : "Y-m-d",
	
	allowDrag : true, 
	allowSelectDays : true, 
	allowSelectWeeks : false, 
	allowMultipleSelection : false,
	allowPastSelection : true,  
	alwaysVisible : false,
	closeable : true,
	
	onChange : null, 
	onPastSelectionError : null,  
	
	selectedDays : [],
	selectedWeeks : [], 
	
	currentYear : null, 
	currentMonth : null, 
	currentDay : null, 
	 
	prepare : function(){
		// set the class attributes
		this.drag = null;
		this.calendar = null;
		
		this.value = "";
		
		this.today = new Date();
		this.workDate = new Date();
		
		this.controller = null;
		this.input = null;
		this.format = "Y-m-d";
		
		this.allowDrag = true;
		this.allowSelectDays = true;
		this.allowSelectWeek = false;
		this.allowMultipleSelection = false;
		this.alwaysVisible = false;
		this.closeable = true;
		
		this.selectedDays = [];			
		this.selectedWeeks = [];
		
		this.currentYear 		= this.today.getFullYear();;
		this.currentMonth 	= this.today.getMonth();
		this.currentDay 		= this.today.getDay();

		// load the style
		syslib.loadStyleForComponent("calendar");
		
		// get the tag attributes
		var attributes = this.__attributes;

		// set the value from the tag attributes
		if(__valid(attributes.format)){
			this.format = attributes.format;
		}
		if(__valid(attributes.drag) && attributes.drag == "false"){
			this.allowDrag = false;
		}
		if(__valid(attributes.selectdays) && attributes.selectdays == "false"){
			this.allowSelectDays = false;
		}
		if(__valid(attributes.selectweeks) && attributes.selectweeks == "true"){
			this.allowSelectWeeks = true;
		}
		if(__valid(attributes.multiple) && attributes.multiple == "true"){
			this.allowMultipleSelection = true;
		}
		if(__valid(attributes.pastselection) && attributes.pastselection == "false"){
			this.allowPastSelection = false;
		}
		if(__valid(attributes.closeable) && attributes.closeable == "false"){
			this.closeable = false;
		}
		if(__valid(attributes.onchange)){
			this.onChange = attributes.onchange;
		} else {
			this.onChange = null;
		}
		if(__valid(attributes.onpastselectionerror)){
			this.onPastSelectionError = attributes.onpastselectionerror;
		} else {
			this.onPastSelectionError = null;
		}
		
		this.weekStart = (syslib.util.valid(attributes.weekstart)) ? attributes.weekstart : Date.weekStartDay;
		this.id = (syslib.util.valid(attributes.id)) ? attributes.id : 'syslib_calendar_' + Math.floor(Math.random() * 10001);
		this.name = (syslib.util.valid(attributes.name)) ? attributes.id : 'syslib_calendar_' + Math.floor(Math.random() * 10001);
		
		return true;
	},

	execute : function(){
		// create the element structure
		var elemtJSON = ["table", {"border" : 0, "cellpadding" : 0, "cellspacing" : 0, "class" : "syslib-calendar-container"},
			["thead", {"innerName" : "calendarHeader"},
				["tr", {"class" : "syslib-calendar-header"},
					["td", {"id" : "calendar_previousYear", "innerName" : "previousYear"}, "&lt;&lt;", 
					 	["input", {"innerName" : "input", "type" : "hidden", "name" : this.name, "id" : this.id}],
					],
					["td", {"id" : "calendar_previousMonth", "innerName" : "previousMonth"}, "&lt;" ],
					["td", {"innerName" : "month", "colspan" : 4, "class" : "syslib-calendar-month"},
					 	"&nbsp;"
					],
					["td", {"id" : "calendar_nextMonth", "innerName" : "nextMonth"}, ">" ],
					["td", {"id" : "calendar_nextYear", "innerName" : "nextYear"}, ">>" ]
				],
				["tr", {"class" : "syslib-calendar-days-header"},
					["td", {"innerName" : "weekLabel"}, "Semana" ],
					["td", {"innerName" : "weekdayLabel_0"}, "&nbsp;" ], 
					["td", {"innerName" : "weekdayLabel_1"}, "&nbsp;" ],
					["td", {"innerName" : "weekdayLabel_2"}, "&nbsp;" ],
					["td", {"innerName" : "weekdayLabel_3"}, "&nbsp;" ],
					["td", {"innerName" : "weekdayLabel_4"}, "&nbsp;" ],
					["td", {"innerName" : "weekdayLabel_5"}, "&nbsp;" ],
					["td", {"innerName" : "weekdayLabel_6"}, "&nbsp;" ]
				]
			],
			["tbody", {"innerName" : "calendarBody", "class" : "calendar_body"}]
		];

		// create the dom element
		var calendar = this.createDOM(elemtJSON);
		
		// check if this calendar use another week start day
		if(this.__attributes.weekstart){
			Date.weekStartDay = parseInt(this.__attributes.weekstart);
		}
		
		// create the days vector
		var days = [];
		
		// define the days label
		if(Date.weekStartDay == 0){
			days = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"];
		} else if(Date.weekStartDay == 1){
			days = ["Seg", "Ter", "Qua", "Qui", "Sex", "Sab", "Dom"];
		} else if(Date.weekStartDay == 2){
			days = ["Ter", "Qua", "Qui", "Sex", "Sab", "Dom", "Seg"];
		} else if(Date.weekStartDay == 3){
			days = ["Qua", "Qui", "Sex", "Sab", "Dom", "Seg", "Ter"];
		} else if(Date.weekStartDay == 4){
			days = ["Qui", "Sex", "Sab", "Dom", "Seg", "Ter", "Qua"];
		} else if(Date.weekStartDay == 5){
			days = ["Sex", "Sab", "Dom", "Seg", "Ter", "Qua", "Qui"];
		} else if(Date.weekStartDay == 6){
			days = ["Sab", "Dom", "Seg", "Ter", "Qua", "Qui", "Sex"];
		}
		
		// set the day labels in the objects
		for(var i = 0; i < days.length; i++){
			// get the object
			var refs 	= this.__refs;
			var obj		= refs["weekdayLabel_"+i];
			
			// set the data
			obj.innerHTML = days[i];
		}
	
		// check if this calendar have a controller, if not, set this calendar as "always visible"
		if(!__valid(this.__attributes.controller)){
			// set this calendar as always visible
			this.alwaysVisible = true;
			this.closeable = false;
		}
		
		// set the basic data navigation events
		syslib.event.listen('click', this.__refs.previousYear, this.onDateChange.applyTo(this));
		syslib.event.listen('click', this.__refs.previousMonth, this.onDateChange.applyTo(this));
		syslib.event.listen('click', this.__refs.nextYear, this.onDateChange.applyTo(this));
		syslib.event.listen('click', this.__refs.nextMonth, this.onDateChange.applyTo(this));
		
	
 		// store the calendar and its references
		this.calendar 	= calendar;
		this.input		= this.__refs.input;
				
		return calendar;
	},

	finalize : function(){
		this.populate();
	},

	onEnterBody : function(){
		// get the attributes
		var attribs = this.__attributes;
		
		// check if this element must be always visible
		if(!this.alwaysVisible){
			// move the element to the body
			this.calendar.parentNode.removeChild(this.calendar);
			document.body.appendChild(this.calendar);
			
			// hide the element
			syslib.element.hide(this.calendar);
		}

		// create the drag
		if(!__valid(attribs.drag) || attribs.drag != "false"){
			this.drag = new syslib.ui.Drag(this.__refs.month, this.calendar, {
				alpha : false
			});	
		}

		// check if this calendar have any controller
		if(__valid(attribs.controller)){
			// get the controller
			var element = __id(attribs.controller);

			// check the controller type
			if(element.tagName.toLowerCase() != "input" || element.type.toLowerCase() != "text"){
				syslib.messages.error("syslib.ui.Calendar.onEnterBody(): Invalid controller element for calendar tag");
				return false;
			}
			
			// set the data
			this.controller = __id(attribs.controller);
			
			// set the position of the calendar
			this.setPositionToElement();

			// set the events of the controller
			syslib.event.listen("focus", this.controller, function(evt){
				// on focus, search the other calendars for hide them
				for(var i = 0; i < syslib.ui.Calendar.GlobalStorage.length; i++){
					var conversor = syslib.ui.Calendar.GlobalStorage[i];
					if(conversor !== this){
						syslib.element.hide(conversor.calendar);
					}
				}
				
				// set the position of this calendar
				this.setPositionToElement();
				
				// show the calendar
				syslib.element.show(this.calendar);
			}.applyTo(this));

			// cancel any key events on the controller
			syslib.event.listen("keydown", this.controller, function(evt){
				syslib.event.stopPropagation(evt);
			}.applyTo(this));

			// store this calendar in the global storage
			syslib.ui.Calendar.GlobalStorage.push(this);
		}
	},

	clear : function(){
		var body = this.__refs.calendarBody;
		for(var i = 0; i < body.childNodes.length; i = 0){
			var child = body.childNodes[i];
			body.removeChild(child);
		}

	},

	populate : function(){
		// create the needed variables
		var workDate 	= this.workDate;
		var line		= this.createEmptyLine();
		var calendar	= this.calendar;

		var currentYear 	= this.currentYear;
		var currentMonth	= this.currentMonth;
		var currentDay		= this.currentDay;

		// start a 32day loop
		for(var i = 1; i <= 32; i++ ){
			// set the work date
			workDate.setDate(i);
			
			// check if the month has been changed
			if(workDate.getDate() < i){
				
				if(workDate.getDay() != Date.weekStartDay){
					
				}
				// create the date of the next month
				var nextMonthDate = new Date();
				
				// set the initial data of the next month date
				nextMonthDate.setFullYear(workDate.getFullYear());
				nextMonthDate.setMonth(workDate.getMonth());
				nextMonthDate.setDate(workDate.getDate() - 1);
				
				// calculate the week end day
				var weekEndDay = (Date.weekStartDay == 0) ? 6 : Date.weekStartDay - 1;
				
				// create the next month days in this calendar while the 
				// previous next day is not the end of the week
				while(nextMonthDate.getDay() != weekEndDay){
					// remove one day of the previous month date
					nextMonthDate.setDate(nextMonthDate.getDate() + 1);
					
					// create the day
					this.createDayElement(nextMonthDate, line, false);
				};
				
				// append the last line
				this.__refs.calendarBody.appendChild(line);
				
				// reset the work date
				workDate.setFullYear(currentYear);
				workDate.setMonth(currentMonth);
				workDate.setDate(currentDay);
				
				// break the loop
				break;
			}

			// check if the current day is the start of a new week
			if(this.workDate.getDay() === Date.weekStartDay || i == 1){
				// check if the actual date is not the start of the month, but is the start of a new week
				if(i != 1){
					// append the last line (week line)
					this.__refs.calendarBody.appendChild(line);
					
					// create a new empty line (week line)
					line = this.createEmptyLine();	
					
					// create the week 
					this.createWeekElement(workDate, line);
				} else {
					// check if the first day of the month starts in the first day of the week to create the days
					// of the previous month that fits the actual month in the calendar
					if(workDate.getDay() != Date.weekStartDay){
						// create the date of the previous month
						var previousMonthDate = new Date();
						
						// set the initial data of the previous month date
						previousMonthDate.setFullYear(workDate.getFullYear());
						previousMonthDate.setMonth(workDate.getMonth());
						previousMonthDate.setDate(workDate.getDate());
						
						// create the previous month days in this calendar while the 
						// previous month day is not an week start day
						do{
							// remove one day of the previous month date
							previousMonthDate.setDate(previousMonthDate.getDate() - 1);
							
							// create the day
							this.createDayElement(previousMonthDate, line, false);
						} while(previousMonthDate.getDay() != Date.weekStartDay);
						
						// create the week 
						this.createWeekElement(previousMonthDate, line);
					} else {
						// just create the week create the week 
						this.createWeekElement(workDate, line);
					}
				}
			}
			
			// create the day
			this.createDayElement(workDate, line);
		}

		// update the month title
		this.__refs.month.innerHTML = syslib.date.make("M/Y", workDate);
	},
	
	createDayElement : function(workDate, line, enabled){
		// get the day object
		var idx = (workDate.getDay() + 1) - Date.weekStartDay;
		if(idx <= 0) idx += 7;
		var day = line.childNodes[idx];
		
		// set the data in the day element
		day.innerHTML 	= workDate.getDate();
		day.id			= "calendar_day_" + syslib.date.make("Ymd", workDate);
		day._formatted	= syslib.date.make(this.format, workDate);
		day._date		= syslib.date.make("Y-m-d", workDate);
		day._selected	= false;
		day._enabled	= true;
		
		// check if the day isn't enabled
		if(enabled === false){
			day._enabled = false;
			day.className	= "syslib-calendar-disabled-day";
		}
		
		// check if the day is a past day
		if(workDate.getTime() < this.today.getTime()){
			day._past = true;
			syslib.css.addClass(day, "syslib-calendar-past-day");
			
		}
		
		// set some events on the day, if its allowed
		if(this.allowSelectDays || this.allowSelectWeeks){
			// check if the day is enabled
			if(day._enabled){
				// mouseover
				syslib.event.listen('mouseover', day, this.onMouseOverDay.applyTo(this));
				
				// mouseout
				syslib.event.listen('mouseout', day, this.onMouseOutDay.applyTo(this));
				
				// click
				syslib.event.listen('click', day, this.onClickDay.applyTo(this));
			}
		}
	}, 
	
	createWeekElement : function(workDate, line){
		// get the week object
		var week = line.childNodes[0];
		
		// set the data
		var weekDate	= new Date(workDate.getFullYear(), workDate.getMonth(), workDate.getDate());
		week.innerHTML 	= weekDate.getWeekOfYear(); 
		week.id			= "calendar_week_" + syslib.date.make("Y_W", weekDate);
		week._formatted	= syslib.date.make("Y.W", weekDate);
		week._date		= syslib.date.make("Y-m-d", weekDate);
		week._selected	= false;
		
		// check if the day is a past day
		if(workDate.getTime() < this.today.getTime()){
			week._past = true;
			syslib.css.addClass(week, "syslib-calendar-past-week");
			
		}
		
		// set some events on the week, if its allowed
		if(this.allowSelectWeeks){
			// mouseover
			syslib.event.listen('mouseover', week, this.onMouseOverWeek.applyTo(this));
			
			// mouseout
			syslib.event.listen('mouseout', week, this.onMouseOutWeek.applyTo(this));
			
			// click
			syslib.event.listen('click', week, this.onClickWeek.applyTo(this));
		}
	}, 

	onDateChange : function(evt){
		// set the needed variables
		var workDate 	= this.workDate;
		var target 		= syslib.event.getElement(evt);
		var action		= target.id;

		var currentYear 	= this.currentYear;
		var currentMonth 	= this.currentMonth;
		var currentDay		= this.currentDay;

		if(action === 'calendar_nextYear'){
			currentYear++;
		}
		if(action === 'calendar_nextMonth'){
			if(currentMonth == 11){
				currentYear++;
				currentMonth = 0;
			} else {
				currentMonth++;
			}
		}
		if(action === 'calendar_previousYear'){
			currentYear--;
		}
		if(action === 'calendar_previousMonth'){
			if(currentMonth === 0){
				currentYear--;
				currentMonth = 11;
			} else {
				currentMonth--;
			}
		}
		
		// set the data on the workdate
		workDate.setFullYear(currentYear);
		workDate.setMonth(currentMonth);

		// set the data into the object
		this.currentYear 	= currentYear;
		this.currentMonth 	= currentMonth;
		this.workDate 		= workDate;

		// repopulate the calendar
		this.clear();
		this.populate();
	},
	
	onMouseOverDay : function(evt){
		// get the target
		var day = syslib.event.getElement(evt);
		
		// check if the element is selected
		if(!day._selected){
			syslib.css.addClass(day, "syslib-calendar-over-day");
		}
	}, 
	
	onMouseOutDay : function(evt){
		// get the target
		var day = syslib.event.getElement(evt);
		
		// remove the class
		syslib.css.removeClass(day, "syslib-calendar-over-day");
	}, 

	onClickDay :  function(target){
		// get the target
		try{
			var day = (typeof target === "string") ? __id(target) : syslib.event.getElement(target);
		} catch(e){
			return false;
		}
		
		// if the day selection is not allowed, check if the week selection is allowed
		if(!this.allowSelectDays){
			if(this.allowSelectWeeks){
				// "click" the week
				this.onClickWeek(day.parentNode.childNodes[0].id);
				return;
			} else {
				// week selection isn't allowed, return false
				return;
			}
		}
		
		// check if the past selection is disabled
		if(!this.allowPastSelection){
			// get the date specification
			var dateSpec = week._date.split("-");
			
			// create the date object of the selected week's first day
			var date = new Date();
			date.setYear(dateSpec[0]);
			date.setMonth((dateSpec[1] - 1));
			date.setDate(dateSpec[2]);
			
			// get the current day
			var today = new Date();
			
			// compare the dates
			if(today.getTime() > date.getTime()){
				// invalid selection, call the events, if setted
				if(__valid(this.onPastSelectionError)){
					eval(this.onPastSelectionError);
				}
				
				// return false
				return false;
			}
		}

		// clear the selected days if this calendar dont allow multiple selection
		if(!this.allowMultipleSelection){
			this.unselectDays();
		}
		
		// select (or unselect) the day
		if(day._selected === true){
			this.unselectDay(day);	
		} else {
			this.selectDay(day);
		}
		
		// update the controller value
		this.updateController();
	
		// hide the calendar if this element is not always visible
		if(!this.alwaysVisible){
			syslib.element.hide(this.calendar);	
		}
	},
	
	onMouseOverWeek : function(evt){
		// get the target
		var week = syslib.event.getElement(evt);
		
		// check if the element is selected
		if(!week._selected){
			syslib.css.addClass(week, "syslib-calendar-over-week");
		}
	}, 
	
	onMouseOutWeek : function(evt){
		// get the target
		var week = syslib.event.getElement(evt);
		
		// remove the class
		syslib.css.removeClass(week, "syslib-calendar-over-week");
	}, 
	
	onClickWeek :  function(target){
		try{
			// get the week
			var week = (typeof target === "string") ? __id(target) : syslib.event.getElement(target);
		} catch(e){
			return false;
		}
		
		
		// check if the past selection is disabled
		if(!this.allowPastSelection){
			// get the date specification
			var dateSpec = week._date.split("-");
			
			// create the date object of the selected week's first day
			var date = new Date();
			date.setYear(dateSpec[0]);
			date.setMonth((dateSpec[1] - 1));
			date.setDate(dateSpec[2]);
			
			// get the current day
			var today = new Date();
			
			// compare the dates
			if(today.getTime() > date.getTime()){
				// invalid selection, call the events, if setted
				if(__valid(this.onPastSelectionError)){
					eval(this.onPastSelectionError);
				}
				
				// return false
				return false;
			}
		}
		
		// clear the selected weeks if this calendar dont allow multiple selection
		if(!this.allowMultipleSelection){
			this.unselectWeeks();
		}
		
		// select (or unselect) the week
		if(week._selected === true){
			this.unselectWeek(week);	
		} else {
			this.selectWeek(week);
		}

		// update the controller value
		this.updateController();
	
		// hide the calendar if this element is not always visible
		if(!this.alwaysVisible){
			syslib.element.hide(this.calendar);	
		}
	},
	
	selectDay : function(dayObj){
		// check if the day is already selected
		if(dayObj._selected === true){
			return true;
		}
		
		// mark this day as selected 
		dayObj.className	= 'syslib-calendar-selected-day';
		dayObj._selected	= true;

		// store it in the selection vector
		this.selectedDays.push(dayObj);
	}, 
	
	unselectDay : function(dayObj){
		// check if the day is already unselected
		if(dayObj._selected === false){
			return true;
		}
		
		// mark it as unselected
		dayObj._selected = false;
		
		// update the class name
		if(!dayObj._enabled){
			dayObj.className = "syslib-calendar-disabled-day";
		} else {
			dayObj.className = "syslib-calendar-normal-day";
		}
		
		// remove from the selection array
		this.selectedDays.pop(dayObj);
	}, 
	
	unselectDays : function(){
		// search the selected days
		for(var i = 0; i < this.selectedDays.length; i++){
			// unselect the day
			this.unselectDay(this.selectedDays[i]);
			
			// clear the selection vector
			this.selectedWeeks = [];
		}
	}, 
	
	selectWeek : function(weekObj){
		// check if the week is already selected
		if(weekObj._selected === true){
			return true;
		}
		
		// get the line
		var lineElements = weekObj.parentNode.childNodes;
		
		// search the line elements
		for(var i = 0; i < lineElements.length; i++){
			// get the element
			var lineElement = lineElements[i];
			
			// check if this element if the week controller
			if(lineElement == weekObj){
				// mark this week as selected 
				weekObj.className 	= 'syslib-calendar-selected-week';
				weekObj._selected		= true;
			} else {
				// element is a day, update his style as a selected day
				lineElement.className 	= 'syslib-calendar-selected-day';
				lineElement._selected	= true;
			}
		}
		
		// store it in the selection vector
		this.selectedWeeks.push(weekObj);
	}, 
	
	unselectWeek : function(weekObj){
		// check if the week is already unselected
		if(weekObj._selected === false){
			return true;
		}
		
		// mark it as unselected
		weekObj.className 	= "syslib-calendar-normal-week";
		weekObj._selected 	= false;
		
		// get the line
		var lineElements = weekObj.parentNode.childNodes;
		
		// search the line elements
		for(var i = 0; i < lineElements.length; i++){
			// get the element
			var lineElement = lineElements[i];
			
			// check if this element if the week controller
			if(lineElement != weekObj){
				// unselect the day
				this.unselectDay(lineElement);
			}
		}
		
		// remove from the selection array
		this.selectedWeeks.pop(weekObj);
	}, 
	
	unselectWeeks : function(){
		// search the selected days
		for(var i = 0; i < this.selectedWeeks.length; i++){
			// unselect the week
			this.unselectWeek(this.selectedWeeks[i]);
			
			// clear the selection vector
			this.selectedWeeks = [];
		}
	}, 
	
	updateController : function(){
		// create the needed variables
		var selection = [];
		
		// merge the weeks and days array and make the array unique
		for(var i = 0; i < this.selectedDays.length; i++){
			var exists = false;
			for(var c = 0; c < selection.length; c++){
				if(selection[c] == this.selectedDays[i]){
					exists = true;
				}
			}
			if(!exists){selection.push(this.selectedDays[i]._formatted)};
		}
		for(var i = 0; i < this.selectedWeeks.length; i++){
			var exists = false;
			for(var c = 0; c < selection.length; c++){
				if(selection[c] == this.selectedWeeks[i]){
					exists = true;
				}
			}
			if(!exists){selection.push(this.selectedWeeks[i]._formatted)};
		}
		
		// update the internal input
		this.input.value = selection.join(";");
		
		if(__valid(this.controller)){
			// update the controller value
			this.controller.value = selection.join(";");
		}
		
		// set the value in the this parser
		this.value = selection.join(";");
		
		// check if the onchange event is valid
		if(__valid(this.onChange)){
			// create a function to parse the onChange data without 'evals'
			var onChangeFunction = new Function(this.onChange).applyTo(this);
			
			// run the created function
			onChangeFunction();
		}
	}, 

	createEmptyLine : function(){
		var lineStructure = ["tr",  
			["td", {"class" : "syslib-calendar-normal-week"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"],
			["td", {"class" : "syslib-calendar-normal-day"}, "&nbsp;"]
		];

		var line = syslib.element.createFromJSON(false, lineStructure);
		return line.element;
	},

	setPositionToElement : function(){
		// check the integrity of the controller
		if(!__valid(this.controller)){
			return true;
		}
		
		var element = this.controller;
		var position	= syslib.ui.position.getOffsets(element);
		var size 		= syslib.ui.size.getOffsets(element);

		syslib.element.updateStyle(this.calendar, {
			"position" : "absolute",
			"margin" : 0,
			"top" : position.y + "px",
			"left" : position.x + size.width + 3 + "px"
		});
	}
});

syslib.ui.Calendar.GlobalStorage = [];